package net.xo68.destiny.starter.common.sched.impl;

import lombok.extern.slf4j.Slf4j;
import net.xo68.destiny.contract.domain.job.TriggerParameter;
import net.xo68.destiny.core.sched.TaskSequencer;
import net.xo68.destiny.core.timingwheel.Timeout;
import net.xo68.destiny.core.timingwheel.TimingWheel;
import net.xo68.destiny.core.timingwheel.TimingWheelTaskSequencer;
import net.xo68.destiny.core.timingwheel.impl.TimingWheelImpl;
import net.xo68.destiny.starter.common.TimingWheelProperties;
import net.xo68.destiny.starter.common.sched.DestinyTimingWheelScheduler;
import net.xo68.destiny.starter.common.sched.TaskTimeoutEventHandler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 时光轮调度实现
 * @author wuxie
 * @version 2020-12-24
 */
@Slf4j
public class DestinyTimingWheelSchedulerImpl implements DestinyTimingWheelScheduler, ApplicationContextAware, SmartInitializingSingleton, DisposableBean {

    private static ApplicationContext applicationContext=null;

    private final TimingWheelProperties timingWheelProperties;
    private final TimingWheel<TriggerParameter> timingWheel;

    public DestinyTimingWheelSchedulerImpl(TimingWheelProperties timingWheelProperties, TaskTimeoutEventHandler taskTimeoutEventHandler) {
        this.timingWheelProperties=timingWheelProperties;
        this.timingWheel=new TimingWheelImpl<>(this.timingWheelProperties.getThreadName(),
                this.timingWheelProperties.getTicksPerWheel(),
                this.timingWheelProperties.getTickDuration(),
                new TaskSequencer(),
                this.timingWheelProperties.getThreadCount(),
                this.timingWheelProperties.getMaxPendingTimeouts()
                ,taskTimeoutEventHandler);
    }

    @Override
    public Set<Timeout<TriggerParameter>> shutdown() {
        return this.timingWheel.shutdown();
    }

    @Override
    public Timeout<TriggerParameter> newTimeout(TriggerParameter triggerParameter, long delay, TimeUnit unit) {
        return this.timingWheel.newTimeout(triggerParameter,delay,unit);
    }

    @Override
    public boolean cancelTimeout(String taskSequence) {
        return this.timingWheel.cancelTimeout(taskSequence);
    }

    @Override
    public TimingWheelTaskSequencer<TriggerParameter> getSequencer() {
        return this.timingWheel.getSequencer();
    }

    @Override
    public void destroy() throws Exception {
        Set<Timeout<TriggerParameter>> timeoutSet=this.timingWheel.shutdown();
        log.info("worker shutdown,timeoutSet: {}",timeoutSet);
    }

    @Override
    public void afterSingletonsInstantiated() {
        this.timingWheel.start();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        DestinyTimingWheelSchedulerImpl.applicationContext=applicationContext;
    }
}
